-- UISkyRevengeMain
-- Create by cheny3
-- 复仇主界面

-- UISkyRevengeMain继承自Layer
UISkyRevengeMain = class("UISkyRevengeMain", function()
    return cc.Layer:create();
end);

function UISkyRevengeMain.create()
    return UISkyRevengeMain.new();
end

-- 内部函数声明
local itemWidthGap   = 270;
local itemheightGap  = 0;
local SCRAP_CLASS_ID = 10000;

-- 构造函数
function UISkyRevengeMain:ctor()
    -- 初始化
    self:setName("UISkyRevengeMain");
    -- 复仇界面
    local node = cc.CSLoader:createNode("layout/sky_city/SkyRevengeMain.csb");
    self:addChild(node);
    self.node = node;

    -- 容器节点
    self.panel = findChildByName(self.node, "CT/panel");
    self.bottomPanel = findChildByName(self.node, "CT/bottom_panel");

    -- 注册事件处理回调函数
    self:registerEventCallback();

    -- 注册点击事件
    self:registerTouchEvent();

    -- 重绘
    self:redraw();

    -- 适配
    self:resize();
end

-- 适配
function UISkyRevengeMain:resize()
    local node = self.node;

    -- bg居中显示并充满整个屏幕
    AlignM.fitToScreen(node, "bg");
    AlignM.fitToScreen(node, "bg2");

    -- CT居中并缩放至合适大小
    AlignM.alignToCenter(node, "CT");

    -- BT置于底部并缩放至合适大小
    AlignM.alignToBottomCenter(node, "BT");
end

-- 重绘界面
function UISkyRevengeMain:redraw()
    -- 绘制标题
    local titleNode = findChildByName(self.node, "CT/title_bar");
    local titleLabel = findChildByName(titleNode, "title");
    titleLabel:setString(getLocStr("be_attack_record"));
    TextStyleM.setArtWordTitleStyle(titleLabel);

    -- 重新初始化数据
    self:initData();
    if #self.recordsList <= 0 then
        -- 没有复仇记录
        self:redrawEmptyRecords();
    else
        -- 有复仇记录
        self:redrawRecords();
    end
end

-- 初始化数据
function UISkyRevengeMain:initData()
    -- 初始化选中规则
    self.recordsList = SkyRelicM.getRobRecord();

    if type(self.selectIndex) == "number" then
        -- 有指定的index，需要保护修正
        if self.selectIndex > #self.recordsList then
            self.selectIndex = 1;
        elseif self.selectIndex <= 0 then
            self.selectIndex = #self.recordsList;
        end
        return;
    end

    -- 初始化index
    if #self.recordsList >= 0 then
        -- 直接获取
        if type(SkyRelicM.getLastRevengeIndex()) == "number" then
            self.selectIndex = SkyRelicM.getLastRevengeIndex();
        else
            -- 初始化是最后一个，因为这个是最新的记录
            self.selectIndex = #self.recordsList;
        end
    else
        self.selectIndex = 0;
    end
end

-- 初始化分组节点
function UISkyRevengeMain:initGrid()
    local itemNode = cc.CSLoader:createNode("layout/sky_city/RevengeItem.csb");
    local widget = replaceNodeWithWidget(itemNode);
    local recordsList = self.recordsList;

    for i = 1, #recordsList do
        local child = widget:clone();
        child:setName("item" .. i);
        self.bottomPanel:addChild(child);
    end

    local child = widget:clone();
    child:setName("selectItem");
    self.panel:addChild(child);
end

-- 计算index代表的分组item和指定的分组的距离
function UISkyRevengeMain:calcDistance(index, targetIndex)
    local selectIndex = targetIndex or self.selectIndex;

    local fristIndex = index - selectIndex
    local secondIndex = index + #self.recordsList - selectIndex;
    local thridIndex = index - #self.recordsList - selectIndex;

    local minDistance = math.min(math.abs(fristIndex), math.abs(secondIndex), math.abs(thridIndex));
    if minDistance == math.abs(fristIndex) then
        return fristIndex;
    elseif minDistance == math.abs(secondIndex) then
        return secondIndex;
    elseif minDistance == math.abs(thridIndex) then
        return thridIndex;
    end
end

-- 计算Index代表的分组item在指定的分组为选中分组情况下的坐标
function UISkyRevengeMain:calcItemPos(index, targetIndex)
    local selectIndex = targetIndex or self.selectIndex;
    local distance = self:calcDistance(index, selectIndex);
    local origin = { ["x"] = self.panel:getContentSize().width / 2, ["y"] = self.panel:getContentSize().height / 2, };

    return cc.p(origin.x + distance * itemWidthGap, origin.y - 20 + math.abs(distance) * itemheightGap);
end

-- 计算Index代表的分组item在指定的分组为选中分组情况下的比例
function UISkyRevengeMain:calcItemScale(index, targetIndex)
    local selectIndex = targetIndex or self.selectIndex;
    local distance = self:calcDistance(index, selectIndex);

    return math.pow(0.88, math.abs(distance)) * 0.9;
end

-- 绘制容器内的item
function UISkyRevengeMain:redrawGroupItems(needRedraw)
    -- 绘制分组item
    local recordsList = self.recordsList;
    local function redrawItem(node, index)
        local revengeInfo = recordsList[index];
        if not revengeInfo then
            -- 有信息过期了？？
            self:redraw();
            return;
        end

        local shipIcon = findChildByName(node, "ship_panel/ship_icon");
        local slimeIcon = findChildByName(node, "slime_icon");
        local nameLabel = findChildByName(node, "name");
        local timeLabel = findChildByName(node, "time");
        local timeIcon = findChildByName(node, "time_icon");
        local nationIcon = findChildByName(node, "nation");
        local mask = findChildByName(node, "mask");

        -- 蒙版
        mask:setVisible(true);
        mask:setOpacity(127);

        -- 选取一只宠物显示
        local pets = revengeInfo["pets"] or {};
        table.sort(pets);
        local randomNum = math.random(math.max(#pets-4, 1), #pets);
        local petId = pets[randomNum];
        -- 如果已经抽取过了，就直接使用上次抽取的
        local oldPetId = SkyRelicM.getShowPetId("revenge", revengeInfo["record_rid"]);
        if oldPetId and table.indexOf(pets, oldPetId) ~= -1 then
            petId = oldPetId;
        else
            -- 记录
            SkyRelicM.setShowPetId("revenge", revengeInfo["record_rid"], petId);
        end

        local iconPath = getHeroIconPath(PetM.getDefaultIcon(petId));
        slimeIcon:loadTexture(iconPath);
        slimeIcon:setScale(1.1);

        -- 飞艇图标
        local shipId = revengeInfo["ship_id"];
        iconPath = getAirShipImgPath(NewAirShipM.query(shipId, "icon"));
        shipIcon:loadTexture(iconPath);
        shipIcon:setScale(0.6);
        shipIcon:setFlippedX(true);

        -- 玩家姓名
        nameLabel:setString(getNickName(revengeInfo["name"]));
        nameLabel:setFontSize(TextStyleM.TEXT_SIZE_SMALL + 2);
        nameLabel:setScale(0.88);
        nameLabel:setTextColor(TextStyleM.TEXT_COLOR_DARK_BROWN);

        -- 倒计时，绑在自己的节点上
        timeLabel:setFontSize(TextStyleM.TEXT_SIZE_SMALL + 2);
        if isIosPlatform() then
            timeLabel:setScale(0.70);
        else
            timeLabel:setScale(0.85);
        end
        timeLabel:setTextColor(TextStyleM.TEXT_COLOR_GRAY);
        timeLabel:stopAllActions();
        timeIcon:setVisible(true);
        timeLabel:setVisible(true);
        local function tick()
            local robWaitTime = FormulaM.invoke("CALC_ROB_FAIL_WAIT_TIME", tonumber(revengeInfo["fail_times"]));
            local leftTime = SkyRelicM.getVaildLeftTime(revengeInfo["record_rid"]);

            if leftTime <= 0 then
                timeLabel:setVisible(false);
                timeIcon:setVisible(false);
                -- 有内容过期了
                self:redraw();
                return;
            end

            local timeText;
            local hour = math.floor(leftTime / 3600);
            local minute = math.floor((leftTime - hour * 3600) / 60);
            local second = math.floor(leftTime % 60);
            timeText = string.format(getLocStr("left_time"), hour, minute, second);
            timeLabel:setString(timeText);
            performWithDelay(timeLabel, tick, 1);
        end
        tick();

        -- 国籍
        iconPath = TopM.queryNationality(revengeInfo["nation"], "icon");
        nationIcon:loadTexture(getNationalityIconPath(iconPath));
        nationIcon:setScale(0.7);
    end

    -- 在bottomPanel绘制所有信息
    for i = 1, #recordsList do
        local child = findChildByName(self.bottomPanel, "item" .. i);
        local descLabel = findChildByName(child, "desc");

        -- 设置位置
        child:setPosition(self:calcItemPos(i));
        child:setScale(self:calcItemScale(i));

        -- 绘制内容
        redrawItem(child, i);

        -- 当前选中的不显示，其他的全部显示
        if i == self.selectIndex or math.abs(self:calcDistance(i)) > 2 then
            child:setVisible(false);
        else
            child:setVisible(true);
        end
    end

    -- 绘制panel中选中信息
    local child = findChildByName(self.panel, "selectItem");
    local mask = findChildByName(child, "mask");

    -- 设置位置和比例
    child:setPosition(self:calcItemPos(self.selectIndex));
    child:setScale(self:calcItemScale(self.selectIndex));

    -- 绘制内容
    redrawItem(child, self.selectIndex);
    mask:setVisible(false);
    -- 轻微的呼吸效果
    self:palyBreathingEffect(child, 1);
end

-- 播放轻微的呼吸效果
function UISkyRevengeMain:palyBreathingEffect(node, oriScale)
    node:stopAllActions();
    node:setScale(oriScale - 0.01);
    local scaleUp = cc.ScaleTo:create(1.0, oriScale + 0.01);
    local scaleDown = cc.ScaleTo:create(1.0, oriScale - 0.01);
    local action = cc.Sequence:create(scaleUp, scaleDown);
    node:runAction(cc.RepeatForever:create(action));
end

-- 移动
function UISkyRevengeMain:moveItems(direction, callback)
    local delay = 0.2;
    local recordsList = self.recordsList;

    for i = 1, #recordsList do
        local child;
        if i == self.selectIndex then
            child = findChildByName(self.panel, "selectItem");
        else
            child = findChildByName(self.bottomPanel, "item" .. i);
        end

        -- 计算这次移动后，选中的item会变成哪一个
        local nextIndex;
        if direction == 1 then
            nextIndex = self.selectIndex + 1;
            if nextIndex > #recordsList then
                nextIndex = 1;
            end
        elseif direction == -1 then
            nextIndex = self.selectIndex - 1;
            if nextIndex <= 0 then
                nextIndex = #recordsList;
            end
        end

        -- 计算child要移动到哪个位置，比例又是多少
        local curPos = self:calcItemPos(i);
        local desPos = self:calcItemPos(i, nextIndex);
        local movePos = cc.p(direction * -1 * itemWidthGap, desPos.y - curPos.y);

        -- 只有当分组只有4组的时候需要这个特殊处理
        -- 当只有4个分组的情况下无法满足往任意一方移动均可保证另一方向有个分组可以移动进来
        if #recordsList == 4 then
            if direction == 1 then
                if i == self.selectIndex - 2 or i == self.selectIndex + 2 then
                    child:setPositionX(desPos.x + itemWidthGap);
                end
            else
                if i == self.selectIndex - 2 or i == self.selectIndex + 2 then
                    child:setPositionX(desPos.x - itemWidthGap);
                end
            end
        end

        local moveBy = cc.MoveBy:create(delay, movePos);
        local scaleTo = cc.ScaleTo:create(delay, self:calcItemScale(i, nextIndex));
        local callFunc = cc.CallFunc:create(function()
            child:setVisible(true);
        end);
        child:runAction(cc.Sequence:create(callFunc, cc.Spawn:create(moveBy, scaleTo)));
    end

    performWithDelay(self, callback, delay);
end

-- 有复仇记录
function UISkyRevengeMain:redrawRecords()
    local panel      = findChildByName(self.node, "CT/panel");
    local subhead    = findChildByName(self.node, "CT/subhead");
    local moneyNode  = findChildByName(self.node, "CT/money_node");
    local scrapNode  = findChildByName(self.node, "CT/scrap_node");
    local emptyDesc  = findChildByName(self.node, "CT/empty_desc");
    local revengeBtn = findChildByName(self.node, "BT/btn_revenge");

    local visibleNodes = {panel, subhead, moneyNode, scrapNode, revengeBtn};
    for _, node in pairs(visibleNodes) do
        node:setVisible(true);
    end
    emptyDesc:setVisible(false);

    local records = self.recordsList;
    TextStyleM.setTextStyle(subhead, TextStyleM.TEXT_SIZE_MIDDLE2, TextStyleM.TEXT_COLOR_ORANGE);
    subhead:setString(string.format(getLocStr("no_revenge_num_tip"), #records));

    -- 移除所有的节点
    self.panel:removeAllChildren();
    self.bottomPanel:removeAllChildren();
    -- 创建格子节点
    self:initGrid();

    -- 绘制容器内的item
    self:redrawGroupItems();

    -- 绘制详细信息
    self:redrawDetail();

    -- 绘制按钮
    self:redrawButton();
end

-- 绘制详细信息
function UISkyRevengeMain:redrawDetail()
    local info = self.recordsList[self.selectIndex];
    local moneyIcon = findChildByName(self.node, "CT/money_node/icon");
    local scrapIcon = findChildByName(self.node, "CT/scrap_node/icon");
    local moneyLabel = findChildByName(self.node, "CT/money_node/text");
    local scrapLabel = findChildByName(self.node, "CT/scrap_node/text");

    -- 计算被抢资源
    local moneyNum = tonumber(info["money"]);
    local scrapNum = tonumber(info["scrap"]) + tonumber(info["ex_resource"]);

    TextStyleM.setTextStyle(moneyLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_LIGHT_BLUE);
    TextStyleM.setTextStyle(scrapLabel, TextStyleM.TEXT_SIZE_SMALL, TextStyleM.TEXT_COLOR_LIGHT_BLUE);
    local moneyName = FieldsM.getFieldName("money");
    local itemName = ItemM.query(SCRAP_CLASS_ID, "name");
    moneyLabel:setString(string.format(getLocStr("item_bonus_format"), moneyName, moneyNum));
    scrapLabel:setString(string.format(getLocStr("item_bonus_format"), itemName, scrapNum));

    -- 居中显示
    local gap = 20;
    local totalWidth = moneyIcon:getContentSize().width + moneyLabel:getContentSize().width + gap;
    moneyIcon:setPositionX(- totalWidth / 2);
    moneyLabel:setPositionX(- totalWidth / 2 + gap + moneyIcon:getContentSize().width - 10);

    totalWidth = scrapIcon:getContentSize().width + scrapLabel:getContentSize().width + gap;
    scrapIcon:setPositionX(- totalWidth / 2);
    scrapLabel:setPositionX(- totalWidth / 2 + gap + scrapIcon:getContentSize().width - 10);
end

-- 重新绘制按钮
function UISkyRevengeMain:redrawButton()
    local info = self.recordsList[self.selectIndex];
    local btnRevenge = findChildByName(self.node, "BT/btn_revenge");

    -- 停止回调
    btnRevenge:stopAllActions();

    -- 时间回调/重新获取时间
    local robWaitTime = FormulaM.invoke("CALC_ROB_FAIL_WAIT_TIME", tonumber(info["fail_times"]));

    local function tick()
        -- 上次掠夺时间
        local lastTime = info["lastRevengeTime"] or 0;
        local leftTime = lastTime + robWaitTime - TimeM.getServerTime();

        if leftTime > 0 then
            -- 显示剩余时间
            btnRevenge:setTitleText(remainingTimeDesc(leftTime));
            performWithDelay(btnRevenge, tick, 1);
        else
            -- 直接显示按钮
            btnRevenge:setTitleText(getLocStr("btn_text_revenge"));
        end
    end
    tick();
end

-- 没有复仇记录
function UISkyRevengeMain:redrawEmptyRecords()
    local panel      = findChildByName(self.node, "CT/panel");
    local subhead    = findChildByName(self.node, "CT/subhead");
    local moneyNode  = findChildByName(self.node, "CT/money_node");
    local scrapNode  = findChildByName(self.node, "CT/scrap_node");
    local emptyDesc  = findChildByName(self.node, "CT/empty_desc");
    local revengeBtn = findChildByName(self.node, "BT/btn_revenge");

    local invisibleNodes = {panel, subhead, moneyNode, scrapNode, revengeBtn};
    for _, node in pairs(invisibleNodes) do
        node:setVisible(false);
    end

    -- 提示没有记录
    emptyDesc:setVisible(true);
    TextStyleM.setTextStyle(emptyDesc, TextStyleM.TEXT_SIZE_LARGE,
        TextStyleM.TEXT_COLOR_ORANGE, nil, nil, nil, nil, nil, TextStyleM.TEXT_SIZE_LARGE + 10);
    emptyDesc:setString(getLocStr("no_revenge_target"));
end

-- 立即复仇
function UISkyRevengeMain:showRevengeTip()
    local info = self.recordsList[self.selectIndex];
    local cost = FormulaM.invoke("CALC_NO_WAIT_TO_ROB_COST");

    -- 确认函数
    local function okFun()
        if ME.user.dbase:query(cost[2], 0) < cost[3] then
            -- 弹出购买钻石提示
            showGemLackConfirm();
            return;
        else
            if not SkyRelicM.isValidRecord(info["record_rid"]) then
                -- 记录已经失效
                alert(getLocStr("revenge_record_unvalid"));
                self:redraw();
                return;
            end
            SkyRelicM.revenge(info["record_rid"], 1);
        end
    end

    local robWaitTime = FormulaM.invoke("CALC_ROB_FAIL_WAIT_TIME", tonumber(info["fail_times"]));
    local lastTime = info["lastRevengeTime"];
    local finalTime = lastTime + robWaitTime;
    local leftTime = finalTime - TimeM.getServerTime();
    local desc = string.format(getLocStr("last_revenge_fail_tip"), remainingTimeDesc(leftTime));

    -- 弹出离开迷宫确认提示框
    confirm2(CONFIRM_TYPE_OK_CANCEL, getLocStr("revenge_tip_title"), desc,
         okFun, nil, getLocStr("btn_text_revenge_now"), getLocStr("btn_text_cancel"),
         { ["cancelColor"] = "blue", ["leftTimeDesc"] = {"revenge", finalTime} });
end

-- 显示/隐藏底部按钮
function UISkyRevengeMain:showBottomBtn(visible)
    local BT = findChildByName(self.node, "BT");
    BT:setVisible(visible);
end

-- 注册事件处理回调函数
function UISkyRevengeMain:registerEventCallback()
    -- 界面析构后，需要清理下
    self:registerScriptHandler(function(eventType)
        if eventType == "exit" then
            EventMgr.removeAll("UISkyRevengeMain");
            -- 设置上次离开的index
            SkyRelicM.setLastRevengeIndex(self.selectIndex);
        elseif eventType == "enter" then
            UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY , TOPMENU_FRAME_RUINS_SCRAP, TOPMENU_FRAME_HEAD_AIRSHIP);
        end
    end);

    -- 注册获得焦点的回调
    EventMgr.register("UISkyRevengeMain", event.FOCUS_CHANGED, function(para)
        if para["get"] == "UISkyRevengeMain" then
            UIMgr:getCurrentScene().topMenu:show(TOPMENU_FRAME_MONEY , TOPMENU_FRAME_RUINS_SCRAP, TOPMENU_FRAME_HEAD_AIRSHIP);
            self:showBottomBtn(true);
        elseif para["lose"] == "UISkyRevengeMain" then
            self:showBottomBtn(false);
        end
    end);

    -- 战斗开始回调
    EventMgr.register("UISkyRevengeMain", event.START_SKY_BATTLE, function(para)
        require "game/ui/form/sky_city/UISkyCityCombat";
        local UISkyCityCombat = UISkyCityCombat.create(para.battle);
        UIMgr.getCurrentScene():addForm(UISkyCityCombat);
    end);

    -- 刷新复仇列表
    EventMgr.register("UISkyRevengeMain", event.REVENGE_LIST_UPDATE, function(para)
        -- 重绘整个界面
        self:redraw();
    end);
end

-- 注册点击事件
function UISkyRevengeMain:registerTouchEvent()
    -- 注册返回按钮点击事件
    local btnBack = findChildByName(self.node,"BT/btn_back");
    local function onBackClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("ship_return");
            -- 关闭当前界面
            UIMgr.getCurrentScene():removeFormByName("UISkyRevengeMain");
        end
    end
    AddBackEventHandler(self, btnBack, onBackClick);
    TextStyleM.setTextStyle(btnBack, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnBack:setTitleText(getLocStr("btn_text_back"));

    -- 复仇按钮
    local btnRevenge = findChildByName(self.node, "BT/btn_revenge");
    local function onRevengeClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");
            -- 打开目标信息界面
            local info = self.recordsList[self.selectIndex];
            require "game/ui/form/sky_city/UIRevengeUserInfo"
            local uiForm = UIRevengeUserInfo.create(info);
            UIMgr.getCurrentScene():addForm(uiForm);
        end
    end
    AddTouchEventListener(btnRevenge, onRevengeClick);
    TextStyleM.setTextStyle(btnRevenge, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnRevenge:setTitleText(getLocStr("btn_text_revenge"));

    -- 记录按钮
    local btnRecord = findChildByName(self.node, "BT/btn_record");
    local function onRecordClick(sender, eventType)
        if eventType == ccui.TouchEventType.ended then
            AudioM.playFx("button_click");
            require "game/ui/form/sky_city/UIRevengeRecords";
            UIMgr.getCurrentScene():removeFormByName("UIRevengeRecords");
            local uiForm = UIRevengeRecords.create();
            UIMgr.getCurrentScene():addForm(uiForm);
        end
    end
    AddTouchEventListener(btnRecord, onRecordClick);
    TextStyleM.setTextStyle(btnRecord, TextStyleM.TEXT_SIZE_MIDDLE, TextStyleM.TEXT_COLOR_BROWN_YELLOW, true);
    btnRecord:setTitleText(getLocStr("btn_text_record"));

    -- panel点击处理
    local function onPanelClick(sender,eventType)
        if self.isMoveing then
            return;
        end

        if eventType == ccui.TouchEventType.ended then
            sender.initMoveX = nil;

            print("打开复仇信息界面")
            local info = self.recordsList[self.selectIndex];
            require "game/ui/form/sky_city/UIRevengeUserInfo"
            local uiForm = UIRevengeUserInfo.create(info);
            UIMgr.getCurrentScene():addForm(uiForm);
        elseif eventType == ccui.TouchEventType.began then
            sender.initMoveX = nil;
        elseif eventType == ccui.TouchEventType.moved then
            local movePos = sender:getTouchMovePosition();
            if not sender.initMoveX then
                sender.initMoveX = movePos.x;
            end

            local direction;
            local moveLen = AlignM.frameSize.width / 10;
            if movePos.x - sender.initMoveX > moveLen then
                -- 往右滑动
                direction = -1;
            elseif movePos.x - sender.initMoveX < -1 * moveLen then
                -- 往左滑动
                direction = 1;
            else
                return;
            end

            -- 先停止点击事件的回调
            self.isMoveing = true;
            sender.initMoveX = movePos.x;

            local function callback()
                self.isMoveing = false;
                if direction == 1 then
                    self.selectIndex = self.selectIndex + 1;
                    if self.selectIndex > #self.recordsList then
                        self.selectIndex = 1;
                    end
                elseif direction == -1 then
                    self.selectIndex = self.selectIndex - 1;
                    if self.selectIndex <= 0 then
                        self.selectIndex = #self.recordsList;
                    end
                end

                -- 重绘下
                self:redraw();
            end

            -- 移动
            self:moveItems(direction, callback);
        end
    end
    self.panel:addTouchEventListener(onPanelClick);
end
